package de.rj.urwalking.data.survey;

import java.util.ArrayList;

import android.content.Context;
import android.util.Log;
import android.util.TypedValue;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.view.animation.AlphaAnimation;
import android.view.animation.Animation;
import android.view.animation.Animation.AnimationListener;
import android.widget.RadioButton;
import android.widget.RadioGroup;
import android.widget.RatingBar;
import android.widget.RatingBar.OnRatingBarChangeListener;
import android.widget.TextView;
import de.rj.urwalking.R;
import de.rj.urwalking.config.Config;
import de.rj.urwalking.config.Constants;

/**
 * 
 * A Question that shows a seven point likert scale as well as an option to rate it as not applicable.
 * 
 * @author rjj
 * 
 */

public class StarRatingQuestion extends Question implements RadioGroup.OnCheckedChangeListener,
		OnRatingBarChangeListener {

	private static final long serialVersionUID = 1L;
	private transient RatingBar ratingBar;
	private transient RadioGroup additionalRadioGroup;

	private transient boolean isShowingAdditionalOptions = false;
	private boolean ignoreBogusCheckedChangedEvent = false;

	public StarRatingQuestion(int id, int itemNumber, String text, int scaleId, int screen) {
		super(id, itemNumber, text, scaleId, screen);

	}

	@Override
	public View buildView(Context context, ViewGroup parent) {
		LayoutInflater inflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
		View view = inflater.inflate(R.layout.question_star_rating, parent, false);

		setQuestionText(view);
		setupLabels(view);
		setupRadioGroups(context, view);
		restoreState();

		return view;
	}

	private void setupLabels(View questionView) {
		TextView extremeLeftLabel = (TextView) questionView.findViewById(R.id.labelLeft);
		TextView extremeRightLabel = (TextView) questionView.findViewById(R.id.labelRight);
		extremeLeftLabel.setText(scale.getLeftExtreme().getTitle());
		extremeRightLabel.setText(scale.getRightExtreme().getTitle());
	}

	private void setupRadioGroups(Context context, View view) {
		// both the actual scale and the n/a options are implemented as separate RadioGroups
		ratingBar = (RatingBar) view.findViewById(R.id.ratingBar);
		ratingBar.setId(id);
		additionalRadioGroup = (RadioGroup) view.findViewById(R.id.naRadioGroup);

		// set regular scalepoints
		ArrayList<ScalePoint> regularScalePoints = scale.getRegularScalePoints();
		ratingBar.setMax(regularScalePoints.size());

		// add additional scale points from database
		for (ScalePoint scalePoint : scale.getAdditionalScalePoints()) {
			RadioButton radioButton = new RadioButton(context);
			radioButton.setText(scalePoint.getTitle());
			radioButton.setTextSize(TypedValue.COMPLEX_UNIT_SP, 20);
			radioButton.setTag(scalePoint.getIntValue());

			if (scalePoint.getIntValue() != -1) {
				radioButton.setVisibility(View.GONE);
			}

			additionalRadioGroup.addView(radioButton);
		}

		ratingBar.setOnRatingBarChangeListener(this);
		additionalRadioGroup.setOnCheckedChangeListener(this);
	}

	/**
	 * checks the corresponding RadioButton in either RadioGroup if there's already an answer
	 */

	private void restoreState() {

		int answerId = getAnswer().getIntAnswer();

		if (answerId == Constants.UNDEFINED) {
			ratingBar.setRating(0);
			additionalRadioGroup.clearCheck();
		} else if (answerId > 0) {
			ratingBar.setRating(answerId);
		} else if (answerId < 0) {
			showAdditionalOptions(additionalRadioGroup);
			int id = additionalRadioGroup.findViewWithTag(answerId).getId();
			additionalRadioGroup.check(id);
		} else {
			ratingBar.setRating(0);
			additionalRadioGroup.clearCheck();
		}

	}

	@Override
	public void onCheckedChanged(RadioGroup group, int checkedId) {
		
		Log.d(Config.TAG, "checkedId:" + checkedId);
		if (ignoreBogusCheckedChangedEvent) {
			ignoreBogusCheckedChangedEvent = false;
			Log.d(Config.TAG, "ignored bogus onCheckedChanged event, clearing flag");
			return;
		}
		if (checkedId == -1) {
			Log.d(Config.TAG, "aborting");
			return;
		}

		ratingBar.setRating(0);

		View v = group.findViewById(checkedId);
		int intAnswer = (Integer) v.getTag();
		updateAnswer(intAnswer);

		if (!isShowingAdditionalOptions) {
			showAdditionalOptions(group);
		}

	}

	private void showAdditionalOptions(RadioGroup radioGroup) {
		//Animation fadeIn = new AlphaAnimation(0, 1);
		//fadeIn.setDuration(500);
		int childcount = radioGroup.getChildCount();
		for (int i = 0; i < childcount; i++) {
			View v = radioGroup.getChildAt(i);
			v.setVisibility(View.VISIBLE);
			//v.startAnimation(fadeIn);

		}

		isShowingAdditionalOptions = true;
	}

	@Override
	public void onRatingChanged(RatingBar ratingBar, float rating, boolean fromUser) {

		Log.d(Config.TAG, "Rating: " + rating);
		if (rating != 0 && additionalRadioGroup.getCheckedRadioButtonId() != -1) {
			// There is a bug in the framework which will fire the currently checked radiobutton once more before
			// actually removing all checks. So let's set this flag to work around it.
			// https://code.google.com/p/android/issues/detail?id=4785
			ignoreBogusCheckedChangedEvent = true;
			Log.d(Config.TAG, "set flag to ignore bogus onCheckedChanged event");

			additionalRadioGroup.check(-1);
		}
		// save the rating
		updateAnswer((int) rating);
		hideAdditionalOptions();

	}

	/**
	 * Hides all radiobuttons except the one showing "keine Angabe"
	 */
	private void hideAdditionalOptions() {

		int childcount = additionalRadioGroup.getChildCount();
		for (int i = 0; i < childcount; i++) {
			final View v = additionalRadioGroup.getChildAt(i);
			if ((Integer) v.getTag() != -1) {
//				Animation fadeOut = new AlphaAnimation(1, 0);
//				fadeOut.setDuration(300);
//				fadeOut.setAnimationListener(new AnimationListener() {
//					@Override
//					public void onAnimationStart(Animation animation) {
//					}
//
//					@Override
//					public void onAnimationRepeat(Animation animation) {
//					}
//
//					@Override
//					public void onAnimationEnd(Animation animation) {
						v.setVisibility(View.GONE);
//					}
//				});
//				v.startAnimation(fadeOut);
			}
		}

		isShowingAdditionalOptions = false;
	}

	@Override
	public boolean hasBeenAnswered() {

		// A StarRatingQuestion is considered as answered if the rating has changed
		// from the initial "undefined" state.
		return getAnswer().getIntAnswer() != Constants.UNDEFINED;
	}
}
